/**
 * Created by kahn on 2018/12/10.
 */
import { Spin } from 'view-design';

let loading;
/**
 * 显示loading层
 * @param   [{string}]    text    [加载效果的文案提示，非必填]
 */
const showLoading = (text = '数据加载中...') => {
    return loading = Spin.show({
        render: (h) => {
            return h('div', [
                h('Icon', {
                    'class': 'demo-spin-icon-load',
                    props: {
                        type: 'ios-loading',
                        size: 18
                    }
                }),
                h('div', text)
            ])
        }
    });
};

/**
 * 关闭loading层
 */
const closeLoading = () => {
    return Spin.hide();
}

/**
 * 各类校验集合fn
 * @param   [{string/number}]   p    [校验内容，必填]
 * @param   [{string}]    t    [校验类型，非必填]
 */
const regExp = (p, t = 'mp') => {        // 正則判断
    switch (t) {
    case 'mp':                      // 手機號
        return /^0?1[2|3|4|5|6|7|8|9][0-9]\d{8}$/.test(p);
    case 'tel':                     // 手機號
        return /^0[\d]{2,3}-[\d]{7,8}$/.test(p);
    case 'id':                      // 身份证
        return /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(p);
    default:
        return;
    }
};


/**
 * 函数节流 防止连续重复调用
 * @param   [{function}]   fn    [要执行函数]
 * @param   [{number}]   t    [控制节流的周期]
 */
const throttle = (fn, t = 500) => {
    let last, timer, interval = t;
    return function () {
        let args = arguments;
        let now = +new Date();
        if (last && now - last < interval) {
            clearTimeout(timer);
            timer = setTimeout(() => {
                last = now;
                fn.apply(this, args);
            }, interval);
        } else {
            last = now;
            fn.apply(this, args);
        }
    }
}

/**
 * 加法运算，避免数据相加小数点后产生多位数和计算精度损失。
 * 
 * @param num1加数1 | num2加数2
 */
const numAdd = (num1, num2, retain = 2) => {
    let baseNum, baseNum1, baseNum2;
    try {
        baseNum1 = num1.toString().split(".")[1].length;
    } catch (e) {
        baseNum1 = 0;
    }
    try {
        baseNum2 = num2.toString().split(".")[1].length;
    } catch (e) {
        baseNum2 = 0;
    }
    baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
    let result = (num1 * baseNum + num2 * baseNum) / baseNum;
    return result.toFixed(retain);
};

/**
 * 减法运算，避免数据相减小数点后产生多位数和计算精度损失。
 * @param num1被减数  |  num2减数
 */
const numSub = (num1, num2, retain = 2) => {
    let baseNum, baseNum1, baseNum2;
    let precision;// 精度
    try {
        baseNum1 = num1.toString().split(".")[1].length;
    } catch (e) {
        baseNum1 = 0;
    }
    try {
        baseNum2 = num2.toString().split(".")[1].length;
    } catch (e) {
        baseNum2 = 0;
    }
    baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
    // precision = (baseNum1 >= baseNum2) ? baseNum1 : baseNum2;
    let result = (num1 * baseNum - num2 * baseNum) / baseNum;
    return result.toFixed(retain);
};
/**
 * 乘法运算，避免数据相乘小数点后产生多位数和计算精度损失。
 * @param num1被乘数 | num2乘数
 */
const numMulti = (num1, num2, retain = 2) => {
    let baseNum = 0;
    try {
        baseNum += num1.toString().split(".")[1].length;
    } catch (e) {
    }
    try {
        baseNum += num2.toString().split(".")[1].length;
    } catch (e) {
    }
    let result = Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", "")) / Math.pow(10, baseNum);
    return result.toFixed(retain);
};
/**
 * 除法运算，避免数据相除小数点后产生多位数和计算精度损失。
 * @param num1被除数 | num2除数
 */
const numDiv = (num1, num2, retain = 2) => {
    let baseNum1 = 0, baseNum2 = 0;
    let baseNum3, baseNum4;
    try {
        baseNum1 = num1.toString().split(".")[1].length;
    } catch (e) {
        baseNum1 = 0;
    }
    try {
        baseNum2 = num2.toString().split(".")[1].length;
    } catch (e) {
        baseNum2 = 0;
    }
    baseNum3 = Number(num1.toString().replace(".", ""));
    baseNum4 = Number(num2.toString().replace(".", ""));
    let result = (baseNum3 / baseNum4) * Math.pow(10, baseNum2 - baseNum1);
    return result.toFixed(retain);
};

const cronValidate = (value) => {
    let cron = value;
    let result = CronExpressionValidator.validateCronExpression(cron);
    if (result == true) {
        return true;
    } else {
        return false
    }
};

const CronExpressionValidator = {
    validateCronExpression: (value) => {
        let results = true;
        if (value == null || value.length == 0) {
            return false;
        }

        // split and test length 
        let expressionArray = value.split(" ");
        let len = expressionArray.length;

        if ((len != 6) && (len != 7)) {
            return false;
        }

        // check only one question mark 
        let match = value.match(/\?/g);
        if (match != null && match.length > 1) {
            return false;
        }

        // check only one question mark 
        let dayOfTheMonthWildcard = "";

        // if appropriate length test parts 
        // [0] Seconds 0-59 , - * / 
        if (CronExpressionValidator.isNotWildCard(expressionArray[0], /[\*]/gi)) {
            if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[0], [0, 59], "seconds")) {
                return false;
            }
        }

        // [1] Minutes 0-59 , - * / 
        if (CronExpressionValidator.isNotWildCard(expressionArray[1], /[\*]/gi)) {
            if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[1], [0, 59], "minutes")) {
                return false;
            }
        }

        // [2] Hours 0-23 , - * / 
        if (CronExpressionValidator.isNotWildCard(expressionArray[2], /[\*]/gi)) {
            if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[2], [0, 23], "hours")) {
                return false;
            }
        }

        // [3] Day of month 1-31 , - * ? / L W C 
        if (CronExpressionValidator.isNotWildCard(expressionArray[3], /[\*\?]/gi)) {
            if (!CronExpressionValidator.segmentValidator("([0-9LWC\\\\,-\\/])", expressionArray[3], [1, 31], "days of the month")) {
                return false;
            }
        } else {
            dayOfTheMonthWildcard = expressionArray[3];
        }

        // [4] Month 1-12 or JAN-DEC , - * / 
        if (CronExpressionValidator.isNotWildCard(expressionArray[4], /[\*]/gi)) {
            expressionArray[4] = this.convertMonthsToInteger(expressionArray[4]);
            if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[4], [1, 12], "months")) {
                return false;
            }
        }

        // [5] Day of week 1-7 or SUN-SAT , - * ? / L C # 
        if (CronExpressionValidator.isNotWildCard(expressionArray[5], /[\*\?]/gi)) {
            expressionArray[5] = this.convertDaysToInteger(expressionArray[5]);
            if (!CronExpressionValidator.segmentValidator("([0-9LC#\\\\,-\\/])", expressionArray[5], [1, 7], "days of the week")) {
                return false;
            }
        } else {
            if (dayOfTheMonthWildcard == String(expressionArray[5])) {
                return false;
            }
        }

        // [6] Year empty or 1970-2099 , - * / 
        if (len == 7) {
            if (CronExpressionValidator.isNotWildCard(expressionArray[6], /[\*]/gi)) {
                if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[6], [1970, 2099], "years")) {
                    return false;
                }
            }
        }
        return true;
    },
    isNotWildCard: (value, expression) => {
        let match = value.match(expression);
        return (match == null || match.length == 0) ? true : false;
    },
    convertDaysToInteger: (value) => {
        let v = value;
        v = v.replace(/SUN/gi, "1");
        v = v.replace(/MON/gi, "2");
        v = v.replace(/TUE/gi, "3");
        v = v.replace(/WED/gi, "4");
        v = v.replace(/THU/gi, "5");
        v = v.replace(/FRI/gi, "6");
        v = v.replace(/SAT/gi, "7");
        return v;
    },
    convertMonthsToInteger: (value) => {
        let v = value;
        v = v.replace(/JAN/gi, "1");
        v = v.replace(/FEB/gi, "2");
        v = v.replace(/MAR/gi, "3");
        v = v.replace(/APR/gi, "4");
        v = v.replace(/MAY/gi, "5");
        v = v.replace(/JUN/gi, "6");
        v = v.replace(/JUL/gi, "7");
        v = v.replace(/AUG/gi, "8");
        v = v.replace(/SEP/gi, "9");
        v = v.replace(/OCT/gi, "10");
        v = v.replace(/NOV/gi, "11");
        v = v.replace(/DEC/gi, "12");
        return v;
    },
    segmentValidator: (expression, value, range, segmentName) => {
        let v = value;
        let numbers = new Array();

        // first, check for any improper segments 
        let reg = new RegExp(expression, "gi");
        if (!reg.test(v)) {
            return false;
        }

        // check duplicate types 
        // check only one L 
        let dupMatch = value.match(/L/gi);
        if (dupMatch != null && dupMatch.length > 1) {
            return false;
        }

        // look through the segments 
        // break up segments on ',' 
        // check for special cases L,W,C,/,#,- 
        var split = v.split(",");
        var i = -1;
        var l = split.length;
        var match;

        while (++i < l) {
            // set vars 
            var checkSegment = split[i];
            var n;
            var pattern = /(\w*)/;
            match = pattern.exec(checkSegment);

            // if just number 
            pattern = /(\w*)\-?\d+(\w*)/;
            match = pattern.exec(checkSegment);

            if (match
                && match[0] == checkSegment
                && checkSegment.indexOf("L") == -1
                && checkSegment.indexOf("l") == -1
                && checkSegment.indexOf("C") == -1
                && checkSegment.indexOf("c") == -1
                && checkSegment.indexOf("W") == -1
                && checkSegment.indexOf("w") == -1
                && checkSegment.indexOf("/") == -1
                && (checkSegment.indexOf("-") == -1 || checkSegment
                .indexOf("-") == 0) && checkSegment.indexOf("#") == -1) {
                    n = match[0];

                    if (n && !(isNaN(n)))
                        numbers.push(n);
                    else if (match[0] == "0")
                        numbers.push(n);
                    continue;
                }
            // includes L, C, or w 
            pattern = /(\w*)L|C|W(\w*)/i;
            match = pattern.exec(checkSegment);

            if (match
                && match[0] != ""
                && (checkSegment.indexOf("L") > -1
                || checkSegment.indexOf("l") > -1
                || checkSegment.indexOf("C") > -1
                || checkSegment.indexOf("c") > -1
                || checkSegment.indexOf("W") > -1 || checkSegment
                    .indexOf("w") > -1)) {
                        // check just l or L 
                        if (checkSegment == "L" || checkSegment == "l")
                            continue;
                        pattern = /(\w*)\d+(l|c|w)?(\w*)/i;
                        match = pattern.exec(checkSegment);

                        // if something before or after 
                        if (!match || match[0] != checkSegment) {
                            continue;
                        }

                        // get the number 
                        var numCheck = match[0];
                        numCheck = numCheck.replace(/(l|c|w)/ig, "");

                        n = Number(numCheck);

                        if (n && !(isNaN(n)))
                            numbers.push(n);
                        else if (match[0] == "0")
                            numbers.push(n);
                        continue;
                    }

            var numberSplit;

            // includes / 
            if (checkSegment.indexOf("/") > -1) {
                // take first # 
                numberSplit = checkSegment.split("/");

                if (numberSplit.length != 2) {
                    continue;
                } else {
                    n = numberSplit[0];

                    if (n && !(isNaN(n)))
                        numbers.push(n);
                    else if (numberSplit[0] == "0")
                        numbers.push(n);
                    continue;
                }
            }

            // includes # 
            if (checkSegment.indexOf("#") > -1) {
                // take first # 
                numberSplit = checkSegment.split("#");

                if (numberSplit.length != 2) {
                    continue;
                } else {
                    n = numberSplit[0];

                    if (n && !(isNaN(n)))
                        numbers.push(n);
                    else if (numberSplit[0] == "0")
                        numbers.push(n);
                    continue;
                }
            }

            // includes - 
            if (checkSegment.indexOf("-") > 0) {
                // take both # 
                numberSplit = checkSegment.split("-");

                if (numberSplit.length != 2) {
                    continue;
                } else if (Number(numberSplit[0]) > Number(numberSplit[1])) {
                    continue;
                } else {
                    n = numberSplit[0];

                    if (n && !(isNaN(n)))
                        numbers.push(n);
                    else if (numberSplit[0] == "0")
                        numbers.push(n);
                    n = numberSplit[1];

                    if (n && !(isNaN(n)))
                        numbers.push(n);
                    else if (numberSplit[1] == "0")
                        numbers.push(n);
                    continue;
                }
            }

        }
        // lastly, check that all the found numbers are in range 
        i = -1;
        l = numbers.length;

        if (l == 0)
            return false;

        while (++i < l) {
            // alert(numbers[i]); 
            if (numbers[i] < range[0] || numbers[i] > range[1]) {
                return false;
            }
        }
        return true;
    }
}

const formatNumber = (n) => {
    const str = n.toString()
    return str[1] ? str : `0${str}`
}

const timeFormat = (value, type = 1) => {
    let year = value.getFullYear(),
        month = formatNumber(value.getMonth() + 1),
        day = formatNumber(value.getDate()),
        hour = formatNumber(value.getHours()),
        min = formatNumber(value.getMinutes()),
        second = formatNumber(value.getSeconds());
    // console.log(year, month, day, hour, min, second)
    if(type == 1) {
        return `${year}-${month}-${day}`;
    }else if(type == 2) {
        return `${year}年${month}月${day}日`;
    }
}


export { showLoading, closeLoading, regExp, throttle, numAdd, numSub, numMulti, numDiv, cronValidate, timeFormat }
